﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using GestureSaver;
using Microsoft.Kinect;
using System.IO;
using System.Globalization;

namespace Experimenter
{
    class Algorithm3 : IAlgorithm
    {
        GestureDB trainingDatabase;
        Dictionary<JointType, double> weights;

        public void Train(GestureDB trainDB)
        {
            this.trainingDatabase = trainDB;
            Common.CenterizeAllGestures(trainingDatabase);
            Common.NormalizeAllShoulderLengths(trainingDatabase); 
            // Weight computation begins
            weights = new Dictionary<JointType, double>();

            var totalDisps = Common.GetTotalDisplacements(this.trainingDatabase);

            foreach (GestureType g in totalDisps.Keys)
            {
                foreach (JointType j in totalDisps[g].Keys)
                {
                    if (weights.ContainsKey(j))
                        weights[j] += totalDisps[g][j];
                    else
                        weights.Add(j, totalDisps[g][j]);
                }
            }

            Common.NormalizeWeights(weights);
            //Weight computation ends
            using (TextWriter writer = File.CreateText(Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + @"\weightsAlg3.txt"))
            {
                for (int j = 0; j < weights.Count; j++)
                {
                    writer.Write(weights.Keys.ElementAt(j) + "  ->  ");
                    writer.WriteLine(weights.Values.ElementAt(j).ToString(CultureInfo.InvariantCulture));
                }
            }
        }

        public GestureType Recognize(Gesture g)
        {
            Common.CenterizeGesture(g);
            Common.NormalizeShoulderLength(g);
            
            double minCost = Double.PositiveInfinity;
            GestureType minCostType = GestureType.UnknownGestureType;

            for (int i = 0; i < trainingDatabase.TotalClassCount; i++)
            {
                double[] costs = new double[trainingDatabase[i].Count];

                for (int j = 0; j < trainingDatabase[i].Count; j++)
                {
                    costs[j] = Common.DTW(g, trainingDatabase[i][j], null, weights); 
                }

                Array.Sort(costs);
                double medianCost = costs[0];

                if (medianCost < minCost)
                {
                    minCost = medianCost;
                    minCostType = trainingDatabase[i][0].gestureType;
                }
            }

            return minCostType;
        }
    }
}
